//GNU C библиотека.
#include <linux/videodev.h>


//Внутренняя библиотека.
#include "vidframe.h"


//===========================================================================//
//=Заголовок: VidFrame::VidFrame() - public
//=Параметры:
//=Описание: Конструктор.
//===========================================================================//
VidFrame::VidFrame(QObject *parent) : QObject(parent)
{
v4l2PixFmt = -1; ffmpegPixFmt = PIX_FMT_NONE;

vData = NULL; deinterlacedData = NULL; length = 0;

cvImage = NULL;

//Создать шрифт для вывода текста на видеокадре.
cvFont.font_face = CV_FONT_VECTOR0;
cvFont.hscale = 0.4f;
cvFont.vscale = 0.4f;
cvFont.shear = 0;
cvFont.thickness = 1;
cvFont.line_type = CV_AA;
}


//===========================================================================//
//=Заголовок: VidFrame::~VidFrame() - public
//=Параметры:
//=Описание: Деструктор.
//===========================================================================//
VidFrame::~VidFrame()
{
if(deinterlacedData) delete[] deinterlacedData;
if(cvImage) cvReleaseImage(&cvImage);
}


//===========================================================================//
//=Заголовок: void VidFrame::setV4L2PixFormat() - public
//=Параметры:
//=Описание: Функция установки V4L2-видеоформата.
//===========================================================================//
void VidFrame::setV4L2PixFormat(int v4l2pixfmt)
{
v4l2PixFmt = v4l2pixfmt;
ffmpegPixFmt = convertV4L2ToFFMPEGPixFormat(v4l2PixFmt);
}


//===========================================================================//
//=Заголовок: int VidFrame::getV4L2PixFormat() - public
//=Параметры:
//=Описание: Функция возврата V4L2-видеоформата.
//===========================================================================//
int VidFrame::getV4L2PixFormat() {return v4l2PixFmt;}


//===========================================================================//
//=Заголовок: void VidFrame::setFFMPEGPixFormat() - public
//=Параметры:
//=Описание: Функция установки FFMPEG-видеоформата.
//===========================================================================//
void VidFrame::setFFMPEGPixFormat(PixelFormat ffmpegpixfmt)
{
ffmpegPixFmt = ffmpegpixfmt;

switch(ffmpegPixFmt)
	{
	case PIX_FMT_YUV420P:  v4l2PixFmt = V4L2_PIX_FMT_YUV420; break;
	case PIX_FMT_YUV422P:  v4l2PixFmt = V4L2_PIX_FMT_YUV422P; break;
	case PIX_FMT_YUYV422:  v4l2PixFmt = V4L2_PIX_FMT_YUYV; break;
	case PIX_FMT_UYVY422:  v4l2PixFmt = V4L2_PIX_FMT_UYVY; break;
	case PIX_FMT_YUV411P:  v4l2PixFmt = V4L2_PIX_FMT_YUV411P; break;
	case PIX_FMT_RGB555:   v4l2PixFmt = V4L2_PIX_FMT_RGB555; break;
	case PIX_FMT_RGB565:   v4l2PixFmt = V4L2_PIX_FMT_RGB565; break;
	case PIX_FMT_BGR24:    v4l2PixFmt = V4L2_PIX_FMT_BGR24; break;
	case PIX_FMT_BGR32:    v4l2PixFmt = V4L2_PIX_FMT_BGR32; break;
	case PIX_FMT_RGB32:    v4l2PixFmt = V4L2_PIX_FMT_RGB32; break;
	case PIX_FMT_GRAY8:    v4l2PixFmt = V4L2_PIX_FMT_GREY; break;
	case PIX_FMT_YUV444P:  v4l2PixFmt = V4L2_PIX_FMT_YUV444; break;
	case PIX_FMT_YUV410P:  v4l2PixFmt = V4L2_PIX_FMT_YUV410; break;
	case PIX_FMT_YUVJ444P: v4l2PixFmt = V4L2_PIX_FMT_JPEG; break;
	default: v4l2PixFmt = V4L2_PIX_FMT_YUV420;
}
}


//===========================================================================//
//=Заголовок: PixelFormat VidFrame::getFFMPEGPixFormat() - public
//=Параметры:
//=Описание: Функция возврата FFMPEG-видеоформата.
//===========================================================================//
PixelFormat VidFrame::getFFMPEGPixFormat() {return ffmpegPixFmt;}


//===========================================================================//
//=Заголовок: void VidFrame::setResolution() - public
//=Параметры:
//=Описание: Функция установки видеоразрешения.
//===========================================================================//
void VidFrame::setResolution(QSize res) {resolution = res;}


//===========================================================================//
//=Заголовок: QSize VidFrame::getResolution() - public
//=Параметры:
//=Описание: Функция возврата видеоразрешения.
//===========================================================================//
QSize VidFrame::getResolution() {return resolution;}


//===========================================================================//
//=Заголовок: int VidFrame::getWidth() - public
//=Параметры:
//=Описание: Функция возврата параметра видеоразрешения.
//===========================================================================//
int VidFrame::getWidth() {return resolution.width();}


//===========================================================================//
//=Заголовок: int VidFrame::getHeight() - public
//=Параметры:
//=Описание: Функция возврата параметра видеоразрешения.
//===========================================================================//
int VidFrame::getHeight() {return resolution.height();}


//===========================================================================//
//=Заголовок: void VidFrame::setBuffer() - public
//=Параметры:
//=Описание: Функция установки видеобуфера.
//===========================================================================//
void VidFrame::setBuffer(uchar *vdata, size_t len)
{
vData = vdata; length = len;

if(deinterlacedData) delete[] deinterlacedData;
deinterlacedData = new uchar[len];
}


//===========================================================================//
//=Заголовок: uchar *VidFrame::getData() - public
//=Параметры:
//=Описание: Функция возврата указателя на видеокадр.
//===========================================================================//
uchar *VidFrame::getData() {return vData;}


//===========================================================================//
//=Заголовок: uchar *VidFrame::getDeinterlacedData() - public
//=Параметры:
//=Описание: Функция возврата указателя на видеокадр.
//===========================================================================//
uchar *VidFrame::getDeinterlacedData() {return deinterlacedData;}


//===========================================================================//
//=Заголовок: size_t VidFrame::getLength() - public
//=Параметры:
//=Описание: Функция возврата размера видеобуфера.
//===========================================================================//
size_t VidFrame::getLength() {return length;}


//===========================================================================//
//=Заголовок: IplImage *VidFrame::getCVImage() - public
//=Параметры:
//=Описание: Функция возврата видеокадра в представлении OpenCV.
//===========================================================================//
IplImage *VidFrame::getCVImage()
{
if(!cvImage)
	cvImage = cvCreateImage(cvSize(resolution.width(), resolution.height()), IPL_DEPTH_8U, 1);

cvImage->imageData = (char*)deinterlacedData;

return cvImage;
}


//===========================================================================//
//=Заголовок: void VidFrame::drawText() - public
//=Параметры:
//=Описание: Функция рисования текста на видеокадре.
//===========================================================================//
void VidFrame::drawText(QString text, int x, int y)
{cvPutText(getCVImage(), (const char*)text.toUtf8(), cvPoint(x, y), &cvFont, cvScalar(255, 255, 255, 0));}


//===========================================================================//
//=Заголовок: void VidFrame::deinterlace() - public
//=Параметры:
//=Описание: Функция удаления чересстрочности видеокадра.
//===========================================================================//
void VidFrame::deinterlace()
{
if(!vData) return;
if(!deinterlacedData) return;
if(ffmpegPixFmt == PIX_FMT_NONE) return;

AVFrame *srcpic = avcodec_alloc_frame();
if(!srcpic) return;
AVFrame *dstpic = avcodec_alloc_frame();
if(!dstpic) return;

avpicture_fill((AVPicture*)srcpic, vData, ffmpegPixFmt, resolution.width(), resolution.height());
avpicture_fill((AVPicture*)dstpic, deinterlacedData, ffmpegPixFmt, resolution.width(), resolution.height());
avpicture_deinterlace((AVPicture *)dstpic, (AVPicture *)srcpic, ffmpegPixFmt, resolution.width(), resolution.height());
av_free(srcpic); av_free(dstpic);
}


//===========================================================================//
//=Заголовок: static PixelFormat VidFrame::convertV4L2ToFFMPEGPixFormat() - public
//=Параметры:
//=Описание: Функция конвертации V4L2-видеоформата в FFMPEG-видеоформат.
//===========================================================================//
PixelFormat VidFrame::convertV4L2ToFFMPEGPixFormat(int v4l2pixfmt)
{
PixelFormat ffmpegpixfmt = PIX_FMT_NONE;

switch(v4l2pixfmt)
	{
	case V4L2_PIX_FMT_YUV420:  ffmpegpixfmt = PIX_FMT_YUV420P; break;
	case V4L2_PIX_FMT_YUV422P: ffmpegpixfmt = PIX_FMT_YUV422P; break;
	case V4L2_PIX_FMT_YUYV:    ffmpegpixfmt = PIX_FMT_YUYV422; break;
	case V4L2_PIX_FMT_UYVY:    ffmpegpixfmt = PIX_FMT_UYVY422; break;
	case V4L2_PIX_FMT_YUV411P: ffmpegpixfmt = PIX_FMT_YUV411P; break;
	case V4L2_PIX_FMT_RGB555:  ffmpegpixfmt = PIX_FMT_RGB555; break;
	case V4L2_PIX_FMT_RGB565:  ffmpegpixfmt = PIX_FMT_RGB565; break;
	case V4L2_PIX_FMT_BGR24:   ffmpegpixfmt = PIX_FMT_BGR24; break;
	case V4L2_PIX_FMT_RGB24:   ffmpegpixfmt = PIX_FMT_RGB24; break;
	case V4L2_PIX_FMT_BGR32:   ffmpegpixfmt = PIX_FMT_BGR32; break;
	case V4L2_PIX_FMT_RGB32:   ffmpegpixfmt = PIX_FMT_RGB32; break;
	case V4L2_PIX_FMT_RGB444:  ffmpegpixfmt = PIX_FMT_RGB32; break;
	case V4L2_PIX_FMT_GREY:    ffmpegpixfmt = PIX_FMT_GRAY8; break;
	case V4L2_PIX_FMT_YUV444:  ffmpegpixfmt = PIX_FMT_YUV444P; break;
	case V4L2_PIX_FMT_YUV410:  ffmpegpixfmt = PIX_FMT_YUV410P; break;
	case V4L2_PIX_FMT_JPEG:    ffmpegpixfmt = PIX_FMT_YUVJ444P; break;
}

return ffmpegpixfmt;
}
